const express = require('express');
const path = require('path');
const multiparty = require('multiparty');
const fse = require('fs-extra');
const cors = require('cors');
const bodyParser = require('body-parser');
const extractExt = (fileName) => {
    return fileName.slice(fileName.lastIndexOf('.'), fileName.length)
}
const app = express();

app.use(bodyParser.json())
const uploadDir = path.resolve(__dirname, 'uploads')
app.use(cors());

app.post('/upload', (req, res) => {
    const form = new multiparty.Form();
    form.parse(req, async (err, fields, files) => {
        if (err) {
            res.status(400).json({
                code: 400,
                msg: '上传失败'
            })
            return
        }
        const fileHash = fields['fileHash'][0];
        const chunkHash = fields['chunkHash'][0];

        // 临时存放目录
        const chunkPath = path.resolve(uploadDir, fileHash)

        if (!fse.existsSync(chunkPath)) {
            await fse.mkdir(chunkPath)
        }
        // 将切片放到这个文件夹中
        await fse.move(files['chunk'][0].path, path.resolve(chunkPath, chunkHash), { overwrite: true })

        res.status(200).json({
            code: 200,
            msg: '上传成功'
        })
    })
})

app.post('/merge', async (req, res) => {
    const { fileHash, fileName, size } = req.body;
    // 如果存在该文件，就没有必要合并
    // 完整的文件路径
    const filePath = path.resolve(uploadDir, fileHash + extractExt(fileName))
    if (fse.existsSync(filePath)) {
        res.status(200).json({
            code: 200,
            msg: '合并成功1'
        })
        return;
    }

    const chunkDir = path.resolve(uploadDir, fileHash)
    if (!fse.existsSync(chunkDir)) {
        res.status(400).json({
            code: 400,
            msg: '合并失败'
        })
        return;
    }

    const chunkPaths = await fse.readdir(chunkDir)
    chunkPaths.sort((a, b) => {
        return a.split('-')[1] - b.split('-')[1]
    })
    const list = chunkPaths.map((chunkPath, index) => {
        return new Promise(res => {
            const chunkItem = path.resolve(chunkDir, chunkPath)
            const readStream = fse.createReadStream(chunkItem)
            const writeStream = fse.createWriteStream(filePath, {
                start: index * size,
                end: (index + 1) * size
            })
            readStream.on('end', async () => {
                await fse.unlink(chunkItem)
                res()
            })
            readStream.pipe(writeStream)
        })

    })

    await Promise.all(list)
    await fse.remove(chunkDir)
    res.status(200).json({
        code: 200,
        msg: '合并成功2'
    })

})

app.post('/verify', async (req, res) => {
    const { fileHash, fileName } = req.body;
    const filePath = path.resolve(uploadDir, fileHash + extractExt(fileName))

    // 返回服务器上已经上传成功的切片
    const chunkDir = path.join(uploadDir, fileHash)
    let chunkPaths = []
    if (fse.existsSync(chunkDir)) {
        chunkPaths = await fse.readdir(chunkDir)
    }

    if (fse.existsSync(filePath)) {
        res.status(200).json({
            code: 200,
            data: {
                shouldUpload: false,
            }
        })
        return
    } else {
        res.status(200).json({
            code: 200,
            data: {
                shouldUpload: true,
                existChunks: chunkPaths
            }
        })
    }
})

app.listen(3003, () => {
    console.log('Server is running on port 3003.......');

})